﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Apache.NMS;
using Apache.NMS.ActiveMQ;
using System.Collections;

namespace AAA.MQ
{
    public class ActiveMQClient :IMQClient
    {
        private const string DEFAULT_QUQUE_NAME = "Queue";
        private const String QUEUE_ADVISORY_DESTINATION = "ActiveMQ.Advisory.";
        private const String TOPIC_ADVISORY_DESTINATION = "ActiveMQ.Advisory.Topic";
        private const String TEMPQUEUE_ADVISORY_DESTINATION = "ActiveMQ.Advisory.TempQueue";
        private const String TEMPTOPIC_ADVISORY_DESTINATION = "ActiveMQ.Advisory.TempTopic";

        private const String ALLDEST_ADVISORY_DESTINATION = QUEUE_ADVISORY_DESTINATION + "," +
                                                           TOPIC_ADVISORY_DESTINATION + "," +
                                                           TEMPQUEUE_ADVISORY_DESTINATION + "," +
                                                           TEMPTOPIC_ADVISORY_DESTINATION;

        private string _strQueueName;
        private IConnection _connection;
        private ISession _session;
        private IMessageConsumer _msgConsumer;
        private string _strBrokerName;
        private string _strClientName;


        #region IMQClient Members

        public ActiveMQClient(string strBrokerName) : this(strBrokerName, null)
        {            
        }

        public ActiveMQClient(string strBrokerName, string strQueueName)
        {
            _strBrokerName = strBrokerName;
            QueueName = strQueueName;
        }

        public string QueueName
        {
            get
            {
                return _strQueueName;
            }
            set
            {
                _strQueueName = value;
            }
        }

        public bool Connect()
        {
            try
            {
                CheckConnection();
                _session = _connection.CreateSession();                
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
            return false;
        }

        private void CheckConnection()
        {
            if (_connection == null)
            {
                IConnectionFactory factory = new ConnectionFactory(_strBrokerName, _strClientName);                
                _connection = factory.CreateConnection();    
            }

            if(_connection.IsStarted == true)
                _connection.Stop();            
            _connection.Start();                    
        }

        public bool Disconnect()
        {
            try
            {
                if (_msgConsumer != null)
                {
                    _msgConsumer.Dispose();
                }
                _session.Close();
                _session.Dispose();
                _connection.Stop();
                _connection.Close();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
            return false;

        }

        public bool Send(IMessage message)
        {
            IMessageProducer msgProducer = null;
            try
            {
                CheckConnection();
                _session = _connection.CreateSession();                
                msgProducer = _session.CreateProducer(_session.GetQueue(QUEUE_ADVISORY_DESTINATION + (QueueName == null ? DEFAULT_QUQUE_NAME : QueueName)));
                msgProducer.DeliveryMode = MsgDeliveryMode.Persistent;
                IObjectMessage oMessage = _session.CreateObjectMessage(message);
                oMessage.Properties.SetLong(message.IdFieldName, message.Id);
                msgProducer.Send(oMessage);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
            finally
            {
                if(msgProducer != null)                
                    msgProducer.Dispose();
                _session.Close();
                _session.Dispose();

            }
            return false;
        }

        public List<IMessage> Peek(string strStatement)
        {
            List<IMessage> lstMessage = new List<IMessage>();
            IQueueBrowser queueBrowser = null;
            try
            {
                CheckConnection();                
                _session = _connection.CreateSession();
                //Console.WriteLine("Peek : " + strStatement);
                queueBrowser = _session.CreateBrowser(_session.GetQueue(QUEUE_ADVISORY_DESTINATION + (QueueName == null ? DEFAULT_QUQUE_NAME : QueueName)), strStatement);
                IEnumerator emuQueue = queueBrowser.GetEnumerator();
                IObjectMessage oMessage;
                
                if(emuQueue != null)
                    while (emuQueue.MoveNext())
                    {
                        oMessage = (IObjectMessage)emuQueue.Current;
                        if (oMessage == null)
                            continue;
                        lstMessage.Add((IMessage)oMessage.Body);
                    }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
            finally
            {
                if (queueBrowser != null)
                {
                    queueBrowser.Close();
                    queueBrowser.Dispose();
                }
                _session.Close();
                _session.Dispose();

            }
            return lstMessage;
        }

        public List<IMessage> Receive(string strStatement)
        {
            List<IMessage> lstMessage = new List<IMessage>();
            IMessageConsumer msgConsumer = null;
            try
            {
                msgConsumer = _session.CreateConsumer(_session.GetQueue(QUEUE_ADVISORY_DESTINATION + (QueueName == null ? DEFAULT_QUQUE_NAME : QueueName)), strStatement);
                IObjectMessage oMessage;
                while ((oMessage = ((IObjectMessage)msgConsumer.Receive())) != null)
                {
                    lstMessage.Add((IMessage)oMessage);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
            finally
            {
                if (msgConsumer != null)
                {
                    msgConsumer.Close();
                    msgConsumer.Dispose();
                }
            }
            return lstMessage;
        }


        public bool Delete()
        {
            try
            {
                _session.DeleteQueue(QUEUE_ADVISORY_DESTINATION + (QueueName == null ? DEFAULT_QUQUE_NAME : QueueName));
                return true;
            }
            catch (Exception ex)
            {
            }
            return false;
        }

        #endregion
    }
}
